// compress.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <tchar.h>
#include <windows.h>

#include "huffman_compress.h"

HANDLE g_source_file = INVALID_HANDLE_VALUE;
HANDLE g_target_file = INVALID_HANDLE_VALUE;

u_long __stdcall ReadSourceData(
    void* Handle, 
    u_char* Buffer, 
    u_long Offset,
    u_long Size
    )
{
    DWORD read_size = 0;
    ::SetFilePointer(g_source_file, Offset, NULL, FILE_BEGIN);
    if (!::ReadFile(g_source_file, Buffer, Size, &read_size, NULL))
    {
        return 0;
    }
    else
    {
        return (u_long)read_size;
    }
}

void __stdcall WriteDestineData(
    void* Handle, 
    u_char* Buffer, 
    u_long Offset,
    u_long Size
    )
{
    DWORD write_size = 0;
    ::SetFilePointer(g_target_file, Offset, NULL, FILE_BEGIN);
    ::WriteFile(g_target_file, Buffer, Size, &write_size, NULL);
}

int _tmain(int argc, _TCHAR* argv[])
{

    if (argc != 4)
    {
        return 0;
    }

    g_source_file = ::CreateFile(
        argv[2], 
        GENERIC_READ, 
        FILE_SHARE_READ, 
        NULL, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, 
        NULL);
    if (g_source_file == INVALID_HANDLE_VALUE)
    {
        return 0;
    }

    g_target_file = ::CreateFile(
        argv[3], 
        GENERIC_WRITE, 
        FILE_SHARE_READ, 
        NULL, 
        CREATE_ALWAYS, 
        FILE_ATTRIBUTE_NORMAL, 
        NULL);
    if (g_target_file == INVALID_HANDLE_VALUE)
    {
        ::CloseHandle(g_source_file);
        return 0;
    }

    switch (argv[1][0])
    {
    case _T('c'):
    case _T('C'):
        compress(NULL, ReadSourceData, WriteDestineData);
        break;

    case _T('d'):
    case _T('D'):
        decompress(NULL, ReadSourceData, WriteDestineData);
        break;

    default:
        break;
    }

    ::CloseHandle(g_source_file);
    ::CloseHandle(g_target_file);

    return 0;
}
